package com.yifeng.repo.micro.service.server.engine.dal.tx;

import com.yifeng.repo.micro.service.server.engine.configure.ForceTransactionProperties;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;
import org.springframework.core.Ordered;
import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;
import org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration;
import org.springframework.transaction.annotation.SpringTransactionAnnotationParser;
import org.springframework.transaction.annotation.TransactionAnnotationParser;
import org.springframework.transaction.config.TransactionManagementConfigUtils;
import org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor;
import org.springframework.transaction.interceptor.TransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionInterceptor;

import javax.annotation.Resource;

/**
 * Created by daibing on 2023/6/9.
 */
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ForceProxyTransactionManagementConfiguration extends ProxyTransactionManagementConfiguration {
    @Resource
    private ForceTransactionProperties properties;

    /**
     * 改写 ProxyTransactionManagementConfiguration#transactionAdvisor，设置order（修改类定义后importingClass丢失，造成注解的order丢失）
     * 在 ConfigurationClassPostProcessor#ImportAwareBeanPostProcessor#postProcessBeforeInitialization
     * @see org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration
     * @see org.springframework.transaction.annotation.EnableTransactionManagement
     * @see org.springframework.transaction.annotation.TransactionManagementConfigurationSelector
     * @see ProxyTransactionManagementConfiguration#transactionAdvisor(TransactionAttributeSource, TransactionInterceptor)
     */
    @Override
    @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
            TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {

        BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
        advisor.setTransactionAttributeSource(transactionAttributeSource);
        advisor.setAdvice(transactionInterceptor);
        advisor.setOrder(Ordered.LOWEST_PRECEDENCE);
        return advisor;
    }

    /**
     * 改写 ProxyTransactionManagementConfiguration#transactionAttributeSource
     * @see org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration
     * @see org.springframework.transaction.annotation.EnableTransactionManagement
     * @see org.springframework.transaction.annotation.TransactionManagementConfigurationSelector
     * @see ProxyTransactionManagementConfiguration#transactionAttributeSource()
     * @see AnnotationTransactionAttributeSource#AnnotationTransactionAttributeSource(TransactionAnnotationParser annotationParser)
     * @see SpringTransactionAnnotationParser
     */
    @Bean
    @Override
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public TransactionAttributeSource transactionAttributeSource() {
        return new AnnotationTransactionAttributeSource(new ForceTargetSpringTransactionAnnotationParser(properties));
    }
}
